home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
Raven 1.2.sit
/
Raven 1.2
/
Source
/
Foundation
/
OS
/
ZPointer.cpp
< prev
next >
Wrap
Text File
|
1997-06-18
|
8KB
|
366 lines
/*
* File: ZPointer.h
* Summary: A class to encapsulate non-relocatable memory.
* Written by: Jesse Jones
*
* Copyright ゥ 1996-1997 Jesse Jones.
* For conditions of distribution and use, see copyright notice in ZTypes.h
*
* Change History (most recent first):
*
* <2> 5/29/97 JDJ No longer uses NewPtr for big blocks.
* <1> 1/14/96 JDJ Created.
*/
#include <ZPointer.h>
#include <ZDebug.h>
#include <ZExceptions.h>
#include <ZMemUtils.h>
#include <ZMiscUtils.h>
#include <ZReferenceCounted.h>
// ===================================================================================
// Helper Functions
// ===================================================================================
//---------------------------------------------------------------
//
// Min
//
//---------------------------------------------------------------
inline ulong Min(ulong x, ulong y)
{
if (x <= y)
return x;
else
return y;
}
#pragma mark -
// ===================================================================================
// class ZPointerRef
// ===================================================================================
class ZPointerRef : public MReferenceCounted {
friend TPointer;
public:
~ZPointerRef();
ZPointerRef();
// Creates a nil pointer.
ZPointerRef(ulong bytes, bool zeroBytes);
ZPointerRef(Ptr takePtr);
const Byte* GetPtr() const;
Byte* GetPtr();
ulong GetSize() const;
void SetSize(ulong bytes, bool zeroBytes);
private:
ZPointerRef(const ZPointerRef& ref);
ZPointerRef& operator=(const ZPointerRef& ref);
private:
Byte* mPtr;
ulong mSize;
};
//---------------------------------------------------------------
//
// ZPointerRef::~ZPointerRef
//
//---------------------------------------------------------------
ZPointerRef::~ZPointerRef()
{
delete [] mPtr;
}
//---------------------------------------------------------------
//
// ZPointerRef::ZPointerRef ()
//
//---------------------------------------------------------------
ZPointerRef::ZPointerRef()
{
mPtr = nil;
mSize = 0;
}
//---------------------------------------------------------------
//
// ZPointerRef::ZPointerRef (ulong, bool)
//
//---------------------------------------------------------------
ZPointerRef::ZPointerRef(ulong bytes, bool zeroBytes)
{
ASSERT(bytes < 16*1024L*1024L);
mPtr = nil;
mSize = bytes;
mPtr = new Byte[mSize];
if (zeroBytes)
ClearMemory(mPtr, mSize);
}
//---------------------------------------------------------------
//
// ZPointerRef::ZPointerRef (Ptr)
//
//---------------------------------------------------------------
ZPointerRef::ZPointerRef(Ptr takePtr)
{
ASSERT(takePtr != nil);
mPtr = reinterpret_cast<Byte*>(takePtr);
mSize = (ulong) GetPtrSize(takePtr);
}
//---------------------------------------------------------------
//
// ZPointerRef::GetPtr const
//
//---------------------------------------------------------------
inline const Byte* ZPointerRef::GetPtr() const
{
ASSERT(mPtr != nil);
return (Byte *) mPtr;
}
//---------------------------------------------------------------
//
// ZPointerRef::GetPtr
//
//---------------------------------------------------------------
inline Byte* ZPointerRef::GetPtr()
{
ASSERT(mPtr != nil);
return (Byte *) mPtr;
}
//---------------------------------------------------------------
//
// ZPointerRef::GetSize
//
//---------------------------------------------------------------
inline ulong ZPointerRef::GetSize() const
{
return mSize;
}
//---------------------------------------------------------------
//
// ZPointerRef::SetSize
//
//---------------------------------------------------------------
void ZPointerRef::SetSize(ulong bytes, bool zeroBytes)
{
ASSERT(bytes < 16*1024L*1024L);
if (bytes != mSize) {
Byte* newPtr = new Byte[bytes]; // Don't need a TRY block because this is the only thing that can fail.
ulong validBytes = Min(bytes, mSize);
BlockMoveData(mPtr, newPtr, validBytes);
delete [] mPtr;
mPtr = newPtr;
if (zeroBytes && bytes > mSize)
ClearMemory(mPtr + mSize, bytes - mSize);
mSize = bytes;
}
}
#pragma mark -
// ===================================================================================
// class TPointer
// ===================================================================================
//---------------------------------------------------------------
//
// TPointer::~TPointer
//
//---------------------------------------------------------------
TPointer::~TPointer()
{
mPointerRef->RemoveReference();
}
//---------------------------------------------------------------
//
// TPointer::TPointer (ulong, bool)
//
//---------------------------------------------------------------
TPointer::TPointer(ulong bytes, bool zeroBytes)
{
mPointerRef = new ZPointerRef(bytes, zeroBytes);
}
//---------------------------------------------------------------
//
// TPointer::TPointer (Ptr)
//
//---------------------------------------------------------------
TPointer::TPointer(Ptr takePtr)
{
try {
mPointerRef = new ZPointerRef(takePtr);
} catch (...) {
DisposePtr(takePtr);
throw;
}
}
//---------------------------------------------------------------
//
// TPointer::TPointer (TPointer)
//
// Does a shallow copy so it's real fast.
//
//---------------------------------------------------------------
TPointer::TPointer(const TPointer& rhs)
{
mPointerRef = rhs.mPointerRef;
mPointerRef->AddReference();
}
//---------------------------------------------------------------
//
// TPointer::operator=
//
//---------------------------------------------------------------
TPointer& TPointer::operator=(const TPointer& rhs)
{
if (mPointerRef != rhs.mPointerRef) {
mPointerRef->RemoveReference();
mPointerRef = rhs.mPointerRef;
mPointerRef->AddReference();
}
return *this;
}
//---------------------------------------------------------------
//
// TPointer::Detach
//
//---------------------------------------------------------------
void TPointer::Detach()
{
if (mPointerRef->GetRefCount() > 1) {
ulong bytes = mPointerRef->GetSize();
ZPointerRef* oldRef = mPointerRef;
ZPointerRef* newRef = new ZPointerRef(bytes, kDontZeroBytes);
BlockMoveData(oldRef->GetPtr(), newRef->GetPtr(), bytes);
mPointerRef->RemoveReference();
mPointerRef = newRef;
}
}
//---------------------------------------------------------------
//
// TPointer::GetPtr const
//
//---------------------------------------------------------------
const Byte* TPointer::GetPtr() const
{
const Byte* ptr = mPointerRef->GetPtr();
return ptr;
}
//---------------------------------------------------------------
//
// TPointer::GetPtr
//
//---------------------------------------------------------------
Byte* TPointer::GetPtr()
{
Byte* ptr = mPointerRef->GetPtr();
return ptr;
}
//---------------------------------------------------------------
//
// TPointer::GetSize
//
//---------------------------------------------------------------
ulong TPointer::GetSize() const
{
ulong size = mPointerRef->GetSize();
return size;
}
//---------------------------------------------------------------
//
// TPointer::SetSize
//
//---------------------------------------------------------------
void TPointer::SetSize(ulong bytes, bool zeroBytes)
{
mPointerRef->SetSize(bytes, zeroBytes);
}
//---------------------------------------------------------------
//
// TPointer::operator==
//
//---------------------------------------------------------------
bool TPointer::operator==(const TPointer& rhs) const
{
bool equal = mPointerRef == rhs.mPointerRef;
if (!equal) {
ulong crc1 = ComputeCRC(this->GetPtr(), this->GetSize());
ulong crc2 = ComputeCRC(rhs.GetPtr(), rhs.GetSize());
equal = crc1 == crc2;
}
return equal;
}